programming4us
           
 
 
Programming

iPad SDK : New Graphics Functionality - We Are All Tool Users (part 5) - The Freehand Tool

- Free product key for windows 10
- Free Product Key for Microsoft office 365
- Malwarebytes Premium 3.7.1 Serial Keys (LifeTime) 2019
12/18/2010 4:16:25 PM

4. The Freehand Tool

Our final tool, the Freehand tool, lets you create a Bézier path. With this tool, you can draw a big string of curved sections by tapping and dragging. Each touch defines a new point on the curve, and dragging immediately after the touch lets you define control points that determine the curvature around that point. While you're dragging a control point around, it's shown with a dashed red line connecting it to the last point you touched, just to make it stand out a little more. To finish off a path, touch the Freehand button in the toolbar (or any other tool button, for that matter). This Freehand tool corresponds to what most people think of as Bézier curves (if they're thinking of Bézier curves at all).

Due to the additional complexity of the interaction with the Freehand tool, we're not going to consider the use of multitouch here. The Freehand tool relies on making a series of points by touching and releasing multiple times, and if we were to track multiple touches, it would be impossible to guess which subsequent touch belonged with which previous touch. Instead, we have a different set of instance variables that are used to hold the state of the current in-progress curve segment, if there is one. As each curve segment is created, it's added to a workingPath object, which is finally sent to the delegate when it's done.

Create a new class called FreehandTool, with the following code:

//  FreehandTool.h
#import <Foundation/Foundation.h>
#import "Tool.h"
@interface FreehandTool : NSObject <Tool> {
id <ToolDelegate> delegate;
UIBezierPath *workingPath;
CGPoint nextSegmentPoint1;
CGPoint nextSegmentPoint2;
CGPoint nextSegmentCp1;
CGPoint nextSegmentCp2;
BOOL isDragging;
BOOL settingFirstPoint;
}
@property (retain, nonatomic) UIBezierPath *workingPath;
+ (FreehandTool *)sharedFreehandTool;
@end

// FreehandTool.m
#import "FreehandTool.h"
#import "PathDrawingInfo.h"
#import "SynthesizeSingleton.h"
@implementation FreehandTool
@synthesize delegate, workingPath;
SYNTHESIZE_SINGLETON_FOR_CLASS(FreehandTool);
- init {
if ((self = [super init])) {
}
return self;
}
- (void)activate {
self.workingPath = [UIBezierPath bezierPath];



settingFirstPoint = YES;
}
- (void)deactivate {
// this is where we finally tell about our path
PathDrawingInfo *info = [PathDrawingInfo pathDrawingInfoWithPath:self.workingPath fillColor:delegate.fillColor strokeColor:delegate.strokeColor];
[delegate addDrawable:info];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
isDragging = YES;
UIView *touchedView = [delegate viewForUseWithTool:self];
UITouch *touch = [[event allTouches] anyObject];
CGPoint touchPoint = [touch locationInView:touchedView];
// set nextSegmentPoint2
nextSegmentPoint2 = touchPoint;
// establish nextSegmentCp2
nextSegmentCp2 = touchPoint;
if (workingPath.empty) {
// this is the first touch in a path, so set the "1" variables as well
nextSegmentCp1 = touchPoint;
nextSegmentPoint1 = touchPoint;
[workingPath moveToPoint:touchPoint];
}
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
isDragging = NO;
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
isDragging = NO;
UIView *touchedView = [delegate viewForUseWithTool:self];
UITouch *touch = [[event allTouches] anyObject];
CGPoint touchPoint = [touch locationInView:touchedView];
nextSegmentCp2 = touchPoint;
// complete segment and add to list
if (settingFirstPoint) {
// the first touch'n'drag doesn't complete a segment, we just
// note the change of state and move along
settingFirstPoint = NO;
} else {
// nextSegmentCp2, which we've been dragging around, is translated
// around nextSegmentPoint2 for creation of this segment.
CGPoint shiftedNextSegmentCp2 = CGPointMake(
nextSegmentPoint2.x + (nextSegmentPoint2.x - nextSegmentCp2.x),
nextSegmentPoint2.y + (nextSegmentPoint2.y - nextSegmentCp2.y));
[workingPath addCurveToPoint:nextSegmentPoint2 controlPoint1:nextSegmentCp1 controlPoint2:shiftedNextSegmentCp2];
// the "2" values are now copied to the "1" variables
nextSegmentPoint1 = nextSegmentPoint2;
nextSegmentCp1 = nextSegmentCp2;
}
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UIView *touchedView = [delegate viewForUseWithTool:self];
UITouch *touch = [[event allTouches] anyObject];
CGPoint touchPoint = [touch locationInView:touchedView];
if (settingFirstPoint) {


nextSegmentCp1 = touchPoint;
} else {
// adjust nextSegmentCp2
nextSegmentCp2 = touchPoint;
}
}
- (void)drawTemporary {
// draw all the segments we've finished so far
[workingPath stroke];
if (isDragging) {
// draw the current segment that's being created
if (settingFirstPoint) {
// just draw a line
UIBezierPath *currentWorkingSegment = [UIBezierPath bezierPath];
[currentWorkingSegment moveToPoint:nextSegmentPoint1];
[currentWorkingSegment addLineToPoint:nextSegmentCp1];
[[delegate strokeColor] setStroke];
[currentWorkingSegment stroke];
} else {
// nextSegmentCp2, which we've
// been dragging around, is translated around nextSegmentPoint2
// for creation of this segment
CGPoint shiftedNextSegmentCp2 = CGPointMake(
nextSegmentPoint2.x + (nextSegmentPoint2.x - nextSegmentCp2.x),
nextSegmentPoint2.y + (nextSegmentPoint2.y - nextSegmentCp2.y));
UIBezierPath *currentWorkingSegment = [UIBezierPath bezierPath];
[currentWorkingSegment moveToPoint:nextSegmentPoint1];
[currentWorkingSegment addCurveToPoint:nextSegmentPoint2 controlPoint1:nextSegmentCp1 controlPoint2:shiftedNextSegmentCp2];
[[delegate strokeColor] setStroke];
[currentWorkingSegment stroke];
}
}
if (!CGPointEqualToPoint(nextSegmentCp2, nextSegmentPoint2) && !settingFirstPoint) {
// draw the guideline to the next segment
UIBezierPath *currentWorkingSegment = [UIBezierPath bezierPath];
[currentWorkingSegment moveToPoint:nextSegmentCp2];
CGPoint shiftedNextSegmentCp2 = CGPointMake(
nextSegmentPoint2.x + (nextSegmentPoint2.x - nextSegmentCp2.x),
nextSegmentPoint2.y + (nextSegmentPoint2.y - nextSegmentCp2.y));
[currentWorkingSegment addLineToPoint:shiftedNextSegmentCp2];


To display the temporary curve that the user is dragging around, we will use a dashed line instead of a solid line, to help make it stand out from the background. This dash pattern specifies that the line will be drawn with 10 pixels in the stroke color we set, then skip 7 pixels, repeating forever.

float dashPattern[] = {10.0, 7.0};
[currentWorkingSegment setLineDash:dashPattern count:2 phase:0.0];
[[UIColor redColor] setStroke];
[currentWorkingSegment stroke];
}
}
- (void)dealloc {
self.workingPath = nil;
self.delegate = nil;
[super dealloc];

}
@end

Now add a few lines to DudelViewController.m to bring it together:

#import "FreehandTool.h"
- (IBAction)touchFreehandItem:(id)sender {
self.currentTool = [FreehandTool sharedFreehandTool];
[freehandButton setImage:[UIImage imageNamed:@"button_bezier_selected.png"]];
}


That's it! The final drawing tool button in our toolbar is complete. Try it out and see how it works. Figure 4 shows a bit of "art" created with our Dudel tools.

Figure 4. Various paths constructed from Bézier curves, using the Freehand, Ellipse, and Pencil tools

Other -----------------
- Security-As-a-[Cloud] Service : Today’s Offerings
- CSS for Mobile Browsers : CSS Sprites
- CSS for Mobile Browsers : Common Patterns (part 4)
- CSS for Mobile Browsers : Common Patterns (part 3) - Titles and Pseudoclasses
- CSS for Mobile Browsers : Common Patterns (part 2) - Rounded corners
- CSS for Mobile Browsers : Common Patterns (part 1) - Absolute and floating positions
- iPad SDK : New Graphics Functionality - The Basic Drawing Architecture
- jQuery 1.3 : Compact forms (part 6)
- jQuery 1.3 : Compact forms (part 5)
- jQuery 1.3 : Compact forms (part 4)
- jQuery 1.3 : Compact forms (part 3)
- jQuery 1.3 : Compact forms (part 2) - AJAX auto-completion
- jQuery 1.3 : Compact forms (part 1) - Placeholder text for fields
- The Art of SEO : Duplicate Content Issues (part 3)
- The Art of SEO : Duplicate Content Issues (part 2) - How Search Engines Identify Duplicate Content
- The Art of SEO : Duplicate Content Issues (part 1) - Consequences of Duplicate Content
- The Art of SEO : Content Optimization (part 2)
- The Art of SEO : Content Optimization (part 1)
- iPad SDK : New Graphics Functionality - Introducing Dudel (part 2)
- iPad SDK : New Graphics Functionality - Introducing Dudel (part 1)
 
 
 
Top 10
 
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 2) - Wireframes,Legends
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 1) - Swimlanes
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Formatting and sizing lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Adding shapes to lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Sizing containers
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 3) - The Other Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 2) - The Data Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 1) - The Format Properties of a Control
- Microsoft Access 2010 : Form Properties and Why Should You Use Them - Working with the Properties Window
- Microsoft Visio 2013 : Using the Organization Chart Wizard with new data
- First look: Apple Watch

- 3 Tips for Maintaining Your Cell Phone Battery (part 1)

- 3 Tips for Maintaining Your Cell Phone Battery (part 2)
programming4us programming4us